import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'package:flutter/scheduler.dart'; //动画减速以做测试用

class AnimationDemo extends MaterialPageRoute<Null> {
    AnimationDemo()
        : super(builder: (BuildContext ctx) {
        return CreateTab();
    });
}

class CreateTab extends StatefulWidget {
    @override
    State<StatefulWidget> createState() => CreateTabState();
}

class CreateTabState extends State<CreateTab> with SingleTickerProviderStateMixin {
    List<Tab> tabs = [];
    TabController controller;
    
    @override
    void initState() {
        tabs.add(Tab(
            text: "方式1",
        ));
        tabs.add(Tab(
            text: "方式2",
        ));
        tabs.add(Tab(
            text: "动画4",
        ));
        controller = TabController(length: tabs.length, vsync: this);
        super.initState();
    }
    
    @override
    void dispose() {
        controller.dispose();
        super.dispose();
    }
    
    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: Text("动画示例"),
            ),
            body: TabBarView(controller: controller, children: [MyAnimationDemo1(), MyAnimationDemo2(), MyAnimationDemo3()]),
            bottomNavigationBar: Material(
                color: Colors.brown,
                child: TabBar(
                    tabs: tabs,
                    controller: controller,
                    indicatorColor: Colors.lightGreen,
                ),
            ));
    }
}

class MyAnimationDemo1 extends StatefulWidget {
    @override
    State<StatefulWidget> createState() => MyAnimState1();
}

class MyAnimState1 extends State<MyAnimationDemo1> with SingleTickerProviderStateMixin {
    Animation animation;
    AnimationController animationController;
    
    @override
    void initState() {
        super.initState();
        animationController = AnimationController(vsync: this, duration: Duration(seconds: 5));
        animation = Tween(begin: 0.0, end: 500.0).animate(animationController)
            ..addListener(() {
                setState(() {
                    //  <----此处调用setSate手动刷新界面
                });
            });
        
        animationController.forward();
    }
    
    @override
    void dispose() {
        animationController.dispose();
        super.dispose();
    }
    
    @override
    Widget build(BuildContext context) {
        return Center(
            child: Container(
                height: animation.value,
                width: animation.value,
                child: FlutterLogo(),
            ),
        );
    }
}

class MyAnimationDemo2 extends StatefulWidget {
    @override
    State<StatefulWidget> createState() => MyAnimState2();
}

class MyAnimState2 extends State<MyAnimationDemo2> with SingleTickerProviderStateMixin {
    Animation animation;
    AnimationController animationController;
    
    @override
    void initState() {
        super.initState();
        animationController = AnimationController(vsync: this, duration: Duration(seconds: 5));
        
        animation = Tween(begin: 0.0, end: 500.0).animate(animationController); // <----这种方式实现的动画不需要手动刷新UI
        animationController.forward();
    }
    
    @override
    void dispose() {
        animationController.dispose();
        super.dispose();
    }
    
    @override
    Widget build(BuildContext context) {
        return AnimatedLogo(animation: animation);
    }
}

class AnimatedLogo extends AnimatedWidget {
    AnimatedLogo({Key key, Animation animation}) : super(key: key, listenable: animation);
    
    @override
    Widget build(BuildContext context) {
        Animation animation = listenable;
        return Center(
            child: Container(
                height: animation.value,
                width: animation.value,
                child: FlutterLogo(),
            ),
        );
    }
}

class MyAnimationDemo3 extends StatefulWidget {
    @override
    State<StatefulWidget> createState() {
        return D3State();
    }
}

class D3State extends State<MyAnimationDemo3> with TickerProviderStateMixin {
    AnimationController controller;
    
    @override
    void initState() {
        super.initState();
        controller = AnimationController(duration: Duration(seconds: 2), vsync: this);
    }
    
    @override
    void dispose() {
        timeDilation = 1.0;
        controller?.dispose();
        super.dispose();
    }
    
    Future _startAnimation() async {
        try {
            await controller
                .forward()
                .orCancel;
            await controller
                .reverse()
                .orCancel;
        } on TickerCanceled {
            print("anim cancel");
        }
    }
    
    @override
    Widget build(BuildContext context) {
        timeDilation = 5.0; //以减速时间放大5倍,变慢5倍
        return GestureDetector(
            onTap: () {
                _startAnimation();
            },
            child: Center(
                child: Container(
                    width: 350.0,
                    height: 350.0,
                    decoration: BoxDecoration(color: Colors.grey.withOpacity(0.5), border: Border.all(color: Colors.blueGrey.withOpacity(0.8))),
                    child: Container(
                        child: D3Box(controller: controller,),
                    ),
                ),
            ),
        );
    }
}

class D3Box extends StatelessWidget {
    D3Box({Key key, this.controller})
        : opacity = Tween<double>(
        begin: 0.5,
        end: 1.0,
    ).animate(CurvedAnimation(parent: controller, curve: Interval(0.0, 1.0, curve: Curves.bounceInOut))),
            rotate = Tween<double>(begin: 0.0, end: 3.1415926 * 4).animate(CurvedAnimation(parent: controller, curve: Interval(0.1, 0.3, curve: Curves.ease))),
            width = Tween<double>(begin: 50.0, end: 200.0).animate(CurvedAnimation(parent: controller, curve: Interval(0.4, 0.6, curve: Curves.fastOutSlowIn))),
            height = Tween<double>(begin: 50.0, end: 200.0).animate(CurvedAnimation(parent: controller, curve: Interval(0.4, 0.6, curve: Curves.fastOutSlowIn))),
            movement = EdgeInsetsTween(begin: EdgeInsets.only(bottom: 10.0, left: 0.0), end: EdgeInsets.only(bottom: 100.0, left: 75.0)).animate(CurvedAnimation(parent: controller, curve: Interval(0.3, 0.4, curve: Curves.fastOutSlowIn))),
            radius = BorderRadiusTween(begin: BorderRadius.circular(0.0), end: BorderRadius.circular(100.0)).animate(CurvedAnimation(parent: controller, curve: Interval(0.6, 0.75, curve: Curves.ease))),
            color = ColorTween(begin: Colors.redAccent, end: Colors.purple).animate(CurvedAnimation(parent: controller, curve: Interval(0.0, 0.75, curve: Curves.linear))),
            super(key: key);
    
    final Animation<double> controller;
    final Animation<double> opacity;
    final Animation<double> width;
    final Animation<double> height;
    final Animation<EdgeInsets> movement;
    final Animation<BorderRadius> radius;
    final Animation<Color> color;
    final Animation<double> rotate;
    
    @override
    Widget build(BuildContext context) {
        return AnimatedBuilder(
            animation: controller,
            builder: (BuildContext ctx, Widget child) {
                return Container(
                    padding: movement.value,
                    transform: Matrix4.identity()
                        ..rotateZ(rotate.value),
                    alignment: Alignment.center,
                    child: Opacity(
                        opacity: opacity.value,
                        child: Container(
                            width: width.value,
                            height: height.value,
                            decoration: BoxDecoration(
                                color: color.value,
                                borderRadius: radius.value,
                                border: Border.all(
                                    color: Colors.grey,
                                    width: 2.0,
                                )),
                        ),
                    ),
                );
            },
        );
    }
}
